function MultiViewer(varargin)
% Data Viewer for Multimodal Data Collected with Controller
%
% Usage: 
%  MultiViever('Argument',Value,...);
%  Data                : MultiModel data in Controller format (obtained from C_loadRecording)
%  Transpose [0]       : Transpose video (Rotate by 90 degree);
%  MirrorX [0]         : Mirror video horizontally
%  MirrorY [0]         : Mirror video vertically
%  CMin [0]            : Minimum of color range
%  CMax [255]          : Maximum of color range
%  TrueLimits [0]      : Compute true color range limits (slower startup)
%  BackRange [ ]       : Averaging range for background subtraction
%  StartFrame [1]      : Frame to start on
%  CurvesByFrame [ ]   : Curves to display for each frame 
%                        (for adding annotations)
%  FIG [1]             : Number of figure to plot into. 
% 
% Keyboard Shortcuts :
%
% Playing: 
% - Arrow left :  one frame back
% - Arrow right :  one frame forward
%
% Visual: 
% - g : show grid
% - +/- : change color range on the spectrogram 
% Author : benglitz@gmail.com


%% PROCESS ARGUMENTS
P =  parsePairs(varargin);
checkField(P,'Data',[]);  
checkField(P,'Transpose',0);
checkField(P,'MirrorX',0);
checkField(P,'MirrorY',0);
checkField(P,'StepSize',0.1); % StepSize for moving with the buttons in seconds 
checkField(P,'Window',2); % A window of 2 seconds around 
checkField(P,'FrameRate',[]);
checkField(P,'CMin',0);
checkField(P,'CMax',255);
checkField(P,'TrueLimits',0);
checkField(P,'StartFrame',1);
checkField(P,'CurvesByFrame',[]);
checkField(P,'Marker','x');
checkField(P,'FIG',1);
checkField(P);

try delete(P.FIG); end

global MV; MV = []; 
MV.FIG=P.FIG;
MV.Colors  =struct('NIDAQ',[0,0,0],'AnalogIn',[0,0,1],'PointGrey',[1,0,0],'ZeroLine',[1,0,0]);
MV.Data = P.Data; 
MV.P = rmfield(P,'Data');
MV.Modules = setdiff( fieldnames(MV.Data),'General');
MV.VideoAvailable = any(strcmp(MV.Modules,'PointGrey'));
MV.AudioAvailable = any(strcmp(MV.Modules,'AnalogIn'));

MV.Trials = MV.Data.NIDAQ.Trials; MV.NTrials = length(MV.Trials); MV.Data.NIDAQ.SRAI = 10000;
for iT =1:MV.NTrials
  L = double(size(MV.Data.NIDAQ.Data(iT).Data.Time,1));
  MV.DAQLengths(iT) = L/MV.Data.NIDAQ.SRAI;
end
MV.DAQStarts = [0,cumsum(MV.DAQLengths(1:end-1))];
for iT=1:length(MV.Data.NIDAQ.Data)
  if ~isempty(MV.Data.NIDAQ.Data(iT).VideoStartTime)
    MV.VideoStarts(iT) = MV.Data.NIDAQ.Data(iT).VideoStartTime(1);
  else 
    MV.VideoStarts(iT) = NaN;
  end
end
MV.TimeTotal = sum(MV.DAQLengths);

% if P.Transpose VV.Video = permute(VV.Video,[2,1,3,4]); end
% if P.MirrorX VV.Video = flipdim(VV.Video,2); end
% if P.MirrorY VV.Video = flipdim(VV.Video,1); end
% 
% VV.NFrames = size(VV.Video,4);
% VV.Dims(1) = size(VV.Video,1);
% VV.Dims(2) = size(VV.Video,2);
% VV.CurrentFrame = P.StartFrame;

%% PREPRARE FIGURE (COMPUTE SIZES)
SS = get(0,'ScreenSize');

figure(P.FIG); set(P.FIG,'Position',[50,400,SS(3:4)-[100,480]],'Toolbar','figure','Name','MultiViewer','NumberTitle','off');
set(P.FIG,'KeyPressFcn',{@LF_KeyPress});
DC = axesDivide(1,[1,0.1],[0.05,0.04,0.93,0.9],[ ],[0.15]);
DCTop = axesDivide([0.4,0.6],1,DC{1},[0.05],[]);
DCTopRight = axesDivide(1,[0.3,0.2,0.3,0.3],DCTop{2},[],[0.1]);
DCBottom = axesDivide([1.5,0.1,0.05,0.05,0.05,0.05],1,DC{2},[0.01],[]);
DS.Video = DCTop{1};
DS.Scrobble = DCBottom{1};
DS.Spectrogram = DCTopRight{1}; 
DS.Audio = DCTopRight{2};
DS.Triggers = DCTopRight{3};
DS.Sensors = DCTopRight{4};
colormap(gray(256)); 

F = fieldnames(DS);
for i=1:length(F); MV.AH.(F{i}) = axes('Pos',DS.(F{i})); box on; end

%% CONTROLS
MV.CurrentTime = 0;
MV.GUI.CurrentTime = uicontrol('style','edit','String',num2str(MV.CurrentTime),...
  'Units','normalized','Position',DCBottom{2},'Callback',{@MV_showData,'setedit'},'Tooltip','Current Time');
MV.GUI.StepSize = uicontrol('style','edit','String',num2str(MV.P.StepSize),...
  'Units','normalized','Position',DCBottom{3},'Tooltip','Step Size for Buttons');
MV.GUI.Help = uicontrol('style','pushbutton','String','Doc',...
  'Units','normalized','Position',DCBottom{4},'Tooltip','Show Documentation','Callback','doc MultiViewer');

ButtonStyles = {'pushbutton','pushbutton'};
Commands = {'Step','Step'};
Strings = {'<','>'};
Tooltips = {'Step Forward','Step Backward'};
W = [1,1,1]; Colors = {0.8*W,0.8*W};
for i=1:length(Strings)
  UH(i) = uicontrol('style',ButtonStyles{i},'String',Strings{i},'Units','normalized','Position',DCBottom{4+i},...
    'Callback',{@MV_showData,Commands{i},Strings{i}},'BackGroundColor',Colors{i},'Tooltip',Tooltips{i},'KeypressFcn',@LF_KeyPress);
end


%% CREATE SCROBBLER
% Plot Markers at the Trial ends (red bars)
axes(MV.AH.Scrobble); hold on;
plot3([MV.CurrentTime,MV.CurrentTime],[0,1],[1,1],'r','Hittest','off'); 
axis([0,MV.TimeTotal,0,1]);
% SHOW ANIMAL POSITION
[AnimalPositionVsTime , AnimalTime , AnimalPositions ] = MV_computeAnimalPosition;
imagesc(AnimalTime,AnimalPositions,AnimalPositionVsTime,'HitTest','off');
caxis([-1,1]);

for iT = 1:MV.NTrials
  if ~isempty(MV.Data.NIDAQ.Data(iT).TrialStartTime)
    MV.TrialStarts(iT) = double(MV.Data.NIDAQ.Data(iT).TrialStartTime);
    MV.TrialStops(iT) = double(MV.Data.NIDAQ.Data(iT).TrialStopTime);
    patch([MV.TrialStarts(iT),MV.TrialStops(iT),MV.TrialStops(iT),MV.TrialStarts(iT)],[0,0,1,1],[0.1,0.1,0.1,0.1],0,'FaceColor',[0.8,0.8,0.8],'HitTest','off','facealpha',0.5)
    text(MV.TrialStarts(iT),1.3,num2str(iT),'Color','k','Horiz','center','FontSize',14);
  end
end
% Plot Scrobbler bar
MV.GUI.CurrentLine = plot3(repmat(MV.CurrentTime,1,2), [0,1],[1,1],'Color',MV.Colors.ZeroLine,'HitTest','off','LineWidth',2);

% Plot horizontal bars in different colors to show when different modalities were recorded
for iT=1:MV.NTrials
  for iM=1:length(MV.Modules)
    cColor = MV.Colors.(MV.Modules{iM});
    ModPos = iM/(length(MV.Modules)+1);
    if iT == 1
      text(-1,ModPos,iM,[MV.Modules{iM},' '],'Horiz','right','Color',cColor,'FontWeight','bold');
    end
    if length(MV.Data.(MV.Modules{iM}).Data)>=iT && ...
      ~isempty(MV.Data.(MV.Modules{iM}).Data(iT).Data.Time)
      cTimes = MV.Data.(MV.Modules{iM}).Data(iT).Data.Time([1,end],1);
      plot3(cTimes,repmat(ModPos,1,2),[1,1],'.-','Color',cColor,'LineWidth',1.5,'HItTest','off');
    end
  end
end


% Activate Scrobbler to choose point in time
text(0,-0.25,'Time [s]  ','Units','n','FontWeight','bold','Horiz','right');
XTicks = C_autobin(1,MV.TimeTotal,10);
set(MV.AH.Scrobble,'ButtonDownFcn',{@MV_scrobblor},'XTick',[1,XTicks(2:end)],'YTick',[],'XGrid','on');
set(P.FIG,'WindowButtonUpFcn','global Scrobbling_ ; Scrobbling_ = 0;'),

%% PREPARE DATA DISPLAY
InputNames = {MV.Data.General.CGSave.Paradigm.HW.Inputs.Name};
axes(MV.AH.Sensors); hold on;
MV.GUI.NIDAQ.SensorInd = find(~cellfun(@isempty,strfind(InputNames,'Pos')));
MV.GUI.NIDAQ.SensorNames = InputNames(MV.GUI.NIDAQ.SensorInd);
set(gca,'XLim',[-MV.P.Window/2,MV.P.Window/2],'YLim',[0,9]);
plot([0,0],[-10,10],'Color',MV.Colors.ZeroLine);
MV.Colors.AniPosP1S1 = [0.5,0,0];
MV.Colors.AniPosP1S2 = [1,0,0];
MV.Colors.AniPosP1S3 = [1,0.3,0.3];
MV.Colors.PlatPosP1 = [1,0.6,0.6];
MV.Colors.AniPosP2S1 = [0,0,0.5];
MV.Colors.AniPosP2S2 = [0,0,1];
MV.Colors.AniPosP2S3 = [0.3,0.3,1];
MV.Colors.PlatPosP2 = [0.6,0.6,1];
MV.Colors.CamPosC1 = [0.3,1,0.3];

for i = 1:length(MV.GUI.NIDAQ.SensorInd)
  cColor = MV.Colors.(MV.GUI.NIDAQ.SensorNames{i});
  MV.GUI.NIDAQ.SensorH(i) = plot(0,0,'Color',cColor);
  text(0.02+(i-1)*0.11,0.9,MV.GUI.NIDAQ.SensorNames{i},'Units','n','FontSize',12,'FontWeight','bold','Color',cColor);
end
ylabel('Voltage [V]'); 
xlabel('Time [s]');

axes(MV.AH.Triggers); hold on;
MV.GUI.NIDAQ.TriggerInd = setdiff([1:length(InputNames)],MV.GUI.NIDAQ.SensorInd);
MV.GUI.NIDAQ.TriggerNames = InputNames(MV.GUI.NIDAQ.TriggerInd);
MV.Colors.Trial = [1,0,0];
MV.Colors.CamStart = [0,0,1];
MV.Colors.CamTrigTo = [0,1,0];
MV.Colors.CamTrigFrom = [0.5,1,0.5];

set(gca,'XLim',[-MV.P.Window/2,MV.P.Window/2],'YLim',[-0.1,5.1]);
plot([0,0],[-10,10],'Color',MV.Colors.ZeroLine);
for i = 1:length(MV.GUI.NIDAQ.TriggerInd)
  cColor = MV.Colors.(MV.GUI.NIDAQ.TriggerNames{i});
  MV.GUI.NIDAQ.TriggerH(i) = plot(0,0,'Color',cColor);
  text(i*0.1,0.9,MV.GUI.NIDAQ.TriggerNames{i},'Units','n','FontSize',12,'FontWeight','bold','Color',cColor);
end
ylabel('Voltage [V]');
MV_showNIDAQ;

%% PREPARE AUDIO DISPLAY
MV.Data.AnalogIn.SRAI = MV.Data.General.CGSave.Parameters.Setup.Audio.SRAI;
SRAI = MV.Data.AnalogIn.SRAI;
axes(MV.AH.Audio); hold on;
set(gca,'YDir','normal','YLim',[-5,5]*std(MV.Data.AnalogIn.Data(1).Data.Analog(3*SRAI:3.5*SRAI,1)),'XLim',[-MV.P.Window/2,MV.P.Window/2]);
plot([0,0],[-10,10],'Color',MV.Colors.ZeroLine);
MV.Colors.AnalogIn = {[1,0,0],[0,0,1]};
for i = 1:2
  MV.GUI.AnalogIn.SoundH(i) = plot(MV.AH.Audio,0,0,'-','Color',MV.Colors.AnalogIn{i}); 
end
ylabel('Voltage [V]');
 
%% PREPARE SPECTROGRAM DISPLAY
axes(MV.AH.Spectrogram); hold on;
MV.GUI.AnalogIn.SpectrogramH = imagesc(0,0,0);
plot([0,0],[0,MV.Data.AnalogIn.SRAI/2],'Color',MV.Colors.ZeroLine);
set(MV.AH.Spectrogram,'YDir','normal','YLim',[0,MV.Data.AnalogIn.SRAI/2],'XLim',[-MV.P.Window/2,MV.P.Window/2]);
ylabel('Freq. [kHz]');
caxis([0,5]);
MV_showAudio;

%% PREPARE VIDEO DISPLAY
axes(MV.AH.Video); hold on;
MV.Data.PointGrey.Dims = MV.Data.General.CGSave.Sessions.Video.Resolution;
MV.GUI.Video.FrameH = imagesc(zeros(MV.Data.PointGrey.Dims)); hold on;
set(MV.GUI.Video.FrameH,'HitTest','off');
set(gca,'XTick',[0:100:MV.Data.PointGrey.Dims(2)],'YTick',[0:100:MV.Data.PointGrey.Dims(1)],...
  'PlotBoxAspectRatio',[MV.Data.PointGrey.Dims([2,1])./max(MV.Data.PointGrey.Dims),1],'PlotBoxAspectRatioMode','manual');
axis tight;
caxis([0,256]);
MV.GUI.Video.TitleH = title(['Video']);

%% CALLBACK FUNCTIONS
function LF_KeyPress(handle,event,FID)

global MV
CC = get(MV.FIG,'CurrentCharacter');
if ~isempty(CC)
  switch int8(CC)
    case 28; MV_showData([],[],'step','<');  % left
    case 29; MV_showData([],[],'step','>'); % right
    case 103; State = get(MV.AH.CurrentFrame,'XGrid'); % g
      if strcmp(State,'on') State = 'off'; else State = 'on'; end;
      set(MV.AH.CurrentFrame,'XGrid',State,'YGrid',State);
    case 113; set(MV.GUI.StartFrame,'String',num2str(MV.CurrentTime)); MV_setLimit(MV.GUI.StartFrame,[],'start');
    case 119; set(MV.GUI.StopFrame,'String',num2str(MV.CurrentTime)); MV_setLimit(MV.GUI.StopFrame,[],'end');
    case 115; MV_saveData;% s save annotations before quitting 
    case 32;  % space = play
      switch get(MV.GUI.PlayForward,'Value')
        case 0; set(MV.GUI.PlayForward,'Value',1); MV_showData([],[],'play','>');
        case 1; set(MV.GUI.PlayForward,'Value',0);
      end
    case {43,61}; % =/+
      CLim = get(MV.AH.Spectrogram,'CLim'); set(MV.AH.Spectrogram,'CLim',1.2*CLim);
    case {45,95}; % -/_
      CLim = get(MV.AH.Spectrogram,'CLim'); set(MV.AH.Spectrogram,'CLim',0.8*CLim);
    case 99; % c = colormap change 
      axes(MV.AH.CurrentFrame);
      if ~MV.Colormap colormap(jet(MV.NColSteps)); MV.Colormap=1;
      else colormap(gray(MV.NColSteps)); MV.Colormap=0;
      end
  end
end
  
function MV_showData(O,E,Command,iFrame)
global MV

switch lower(Command)
  case 'set'; MV.CurrentTime = iFrame;
  case 'setedit'; MV.CurrentTime= str2num(get(O,'String'));
  case 'setvisual'; MV.CurrentTime = get(O,'CurrentPoint');MV.CurrentTime = round(MV.CurrentTime(1,1));
  case 'step';   
    MV.P.StepSize = str2num(get(MV.GUI.StepSize,'String'));
    switch iFrame
      case '>'; MV.CurrentTime = MV.CurrentTime + MV.P.StepSize; 
      case '<'; MV.CurrentTime = MV.CurrentTime - MV.P.StepSize; 
    end
  case 'redraw';
end

MV.CurrentTime = min([MV.TimeTotal,MV.CurrentTime]);
MV.CurrentTime= max([0,MV.CurrentTime]);

set(MV.GUI.CurrentTime,'String',num2str(MV.CurrentTime));
set(MV.GUI.CurrentLine,'XData',[MV.CurrentTime,MV.CurrentTime]);

MV_showNIDAQ % Shows NIDAQ ( SENSORS and TRIGGERS )
if MV.AudioAvailable MV_showAudio; end % Shows AnalogIn (SoundPressure and Spectrogram) 
if MV.VideoAvailable MV_showVideo; end % Shows Video Data (FRAME)

function [cTime,cData] = MV_getCurrentData(Module)
    global MV
   StartTime = MV.CurrentTime-MV.P.Window/2;
   StopTime = MV.CurrentTime+MV.P.Window/2;
   TrialStart = find(MV.DAQStarts<StartTime,1,'last');
   TrialStop = find(StopTime>MV.DAQStarts,1,'last');
   FillZerosStart = isempty(TrialStart);
   FillZerosStop = isempty(TrialStop);
   
   % FIND THE STARTING AND STOPPING POINT FOR THE PLOTTING (USES COARSE
   % SEARCH FIRST FOR SPEED UP);
   Factor = 1000;
   if FillZerosStart;     cIndStart = [];
   else
     cIndStartCoarse = find(MV.Data.(Module).Data(TrialStart).Data.Time(Factor:Factor:end,1) >= StartTime,1,'first');
     if ~isempty(cIndStartCoarse)
       cInds = cIndStartCoarse*Factor+[-Factor+1:0];
       cIndStartFine = find(MV.Data.(Module).Data(TrialStart).Data.Time(cInds,1) >= StartTime,1,'first');
       cIndStart = (cIndStartCoarse-1)*Factor + cIndStartFine;
     else 
       cIndStart = [];
     end
   %    IndStart = find_halfspace_mex(MV.(Module).Times,StartTime);
   end
   
   if FillZerosStop;      cIndStop = [];
   else
     cIndStopCoarse = find(MV.Data.(Module).Data(TrialStop).Data.Time(Factor:Factor:end,1) <= StopTime,1,'last');
     if ~isempty(cIndStopCoarse)
       cInds = [(cIndStopCoarse-1)*Factor+1  : min((cIndStopCoarse+1)*Factor,length(MV.Data.(Module).Data(TrialStop).Data.Time))];
       cIndStopFine = find(MV.Data.(Module).Data(TrialStop).Data.Time(cInds,1) <= StopTime,1,'last');
       cIndStop = (cIndStopCoarse-1)*Factor + cIndStopFine;
     else 
       cIndStop = [];
     end
    % cIndStop = find(MV.Data.(Module).Data(TrialStop).Data.Time(:,1) <= StopTime,1,'last');
   end

   if TrialStart == TrialStop
     Inds = [cIndStart:cIndStop];
     cTime = MV.Data.(Module).Data(TrialStart).Data.Time(Inds,1);
     cData = MV.Data.(Module).Data(TrialStart).Data.Analog(Inds,:);
   else
     if FillZerosStart
       cTime = MV.Data.(Module).Data(TrialStop).Data.Time(1:cIndStop,1);
       cData = MV.Data.(Module).Data(TrialStop).Data.Analog(1:cIndStop,:);
     elseif FillZerosStop
       cTime = MV.Data.(Module).Data(TrialStart).Data.Time(cIndStart:end,1);
       cData = MV.Data.(Module).Data(TrialStart).Data.Analog(cIndStart:end,:);       
     else
       cTime = ...
         [MV.Data.(Module).Data(TrialStart).Data.Time(cIndStart:end,1);...
         MV.Data.(Module).Data(TrialStop).Data.Time(1:cIndStop,1)];
       cData = ...
         [MV.Data.(Module).Data(TrialStart).Data.Analog(cIndStart:end,:);...
         MV.Data.(Module).Data(TrialStop).Data.Analog(1:cIndStop,:)];
     end
   end
   % find_halfspace_mex finds the next index below the closest index (from below)
   % cIndStart = find(MV.(Module).Times > MV.CurrentTime-MV.P.Window/2,1,'first');
   %   IndStart = find_halfspace_mex(MV.(Module).Times,MV.CurrentTime-MV.P.Window/2);
   % cIndStop = find(MV.(Module).Times < MV.CurrentTime+MV.P.Window/2,1,'last');
   %   IndStop = find_halfspace_mex(MV.(Module).Times,MV.CurrentTime+MV.P.Window/2);
   if size(cTime,1) ~= size(cData,1) keyboard; end   
  
function MV_showNIDAQ
   global MV;
 
   [cTime,cData] = MV_getCurrentData('NIDAQ');
   
   % FILL THE SENSOR PLOT
   for i=1:length(MV.GUI.NIDAQ.SensorInd)
     set(MV.GUI.NIDAQ.SensorH(i),'YData',cData(:,MV.GUI.NIDAQ.SensorInd(i)) +3*floor((i-1)/4),'XData',cTime-MV.CurrentTime);
   end

   % FILL THE TRIGGER PLOT
   for i=1:length(MV.GUI.NIDAQ.TriggerInd)
     set(MV.GUI.NIDAQ.TriggerH(i),'YData',cData(1:2:end,MV.GUI.NIDAQ.TriggerInd(i))/5+1.1*(i-1),'XData',cTime(1:2:end)-MV.CurrentTime);
   end

function MV_showAudio
  global MV;
  SRAI = MV.Data.General.CGSave.Parameters.Setup.Audio.SRAI;
  NFFT = 512;
  
  %tic;
  [cTime,cData] = MV_getCurrentData('AnalogIn');
 % T(1) = toc;

  if ~isempty(cTime)
    %tic;
    % FILL THE TRIGGER PLOT
    for i=1:size(cData,2)
      set(MV.GUI.AnalogIn.SoundH(i),'YData',cData(1:4:end,i),'XData',cTime(1:4:end)-MV.CurrentTime);
    end
   % T(2) = toc;
   if length(cData) > NFFT
     [ S , F ,T] = spectrogram(double(cData(:,1)),NFFT,NFFT/2,NFFT,SRAI);
     set(MV.GUI.AnalogIn.SpectrogramH,'CData',abs(S),'XData',T- (MV.CurrentTime-cTime(1)),'YData',F);
   end
   % fprintf('NIDAQ: %f  Audio : %f  Video: %f \n',T(1),T(2),T(3));

  else 
    for i=1:2
      set(MV.GUI.AnalogIn.SoundH(i),'YData',[],'XData',[]);
    end
    set(MV.GUI.AnalogIn.SpectrogramH,'CData',NaN);
  end
  
function MV_showVideo
  global MV;
  
  Trial = find(MV.CurrentTime>MV.VideoStarts,1,'last');
  if ~isempty(Trial) && Trial > 0
    cFrame = find(MV.Data.PointGrey.Data(Trial).Data.Time(:,1) >= MV.CurrentTime,1,'first');
    if ~isempty(cFrame)
      cData = MV.Data.PointGrey.Data(Trial).Data.Frames(:,:,1,cFrame);
      set(MV.GUI.Video.FrameH,'CData',cData);
      set(MV.GUI.Video.TitleH,'String',['Video : Trial ',num2str(Trial),' Frame : ' num2str(cFrame)])
    end
  end
  
function MV_scrobblor(O,E)

  global MV;
  
  AxPos = get(MV.AH.Scrobble,'Position');
  FigPos = get(MV.FIG,'Position');
  Pixels = AxPos(3)*FigPos(3);
  TimeTotal = MV.TimeTotal;
  TimePerPixel = TimeTotal/Pixels;
  AxisStartPixels =  FigPos(1) + AxPos(1)*FigPos(3);
 % LastPoint = [-inf,-inf];
  
  SelType = get(MV.FIG,'SelectionType');
  switch SelType
    case 'normal';
      global Scrobbling_ ; Scrobbling_ =1;
      
      while Scrobbling_
        CurrentPoint = get(0,'PointerLocation');
        CurrentTime  = TimePerPixel*(CurrentPoint(1)-AxisStartPixels);
        MV_showData([],[],'set',CurrentTime);
        pause(0.04);
      end
      
    case {'alt','extend'};
  end

  function [AnimalPositionVsTime,AnimalTime,AnimalPositions] = MV_computeAnimalPosition
    global MV;
    % Collect Data
    StepSize = 100;
    HW = MV.Data.General.CGSave.Paradigm.HW;
    AnimalSensors  = HW.AnimalSensorsPhys;
    Thresholds = [HW.Inputs.Threshold];
    AnimalThresholds = Thresholds(AnimalSensors);
    InputStates = [];
    for iT = 1:length(MV.Data.NIDAQ.Data)
      InputStates = [InputStates;MV.Data.NIDAQ.Data(iT).Data.Analog(:, AnimalSensors )];
    end
    InputStates = InputStates(StepSize:StepSize:end,:);
    
    % Threshold Data
    for i=1:size(InputStates,2)
      InputStates(:,i) = InputStates(:,i) > AnimalThresholds(i);
    end
    AnimalPositionVsTime = InputStates';
    AnimalTime = [1:size(AnimalPositionVsTime,2)]/(MV.Data.NIDAQ.SRAI/StepSize); 
    NPos =size(AnimalPositionVsTime,1);
    AnimalPositions = linspace(1/(2*NPos), 1-1/(2*NPos),NPos);
        
    
    
    
